"""结合回测过程数据，生成md文件"""
import os

import matplotlib
import pandas as pd

from module.dynamic_module.fighting.model import FightingModel
from core.constant import *
from mdutils.mdutils import MdUtils
import matplotlib.pyplot as plt

matplotlib.use("Agg")

# 设置字体属性，确保中文正常显示
plt.rcParams['font.sans-serif'] = ['SimHei']  # 指定默认字体为SimHei，这是一个支持中文的字体
plt.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号'-'显示为方块的问题


def draw_backtest_figure(df: pd.DataFrame, fig_path):

    # # Rename the first column to 'time' for clarity
    # df.rename(columns={'Unnamed: 0': 'time'}, inplace=True)

    # Convert 'time' column to datetime format
    # df['datetime'] = pd.to_datetime(df['datetime'])

    # Set 'time' as the index
    # df.set_index('datetime', inplace=True)

    # Create a figure with two subplots, one above the other
    fig, (ax1, ax2) = plt.subplots(nrows=2, ncols=1, sharex=True, figsize=(16, 8),
                                   gridspec_kw={'height_ratios': [3, 1]})

    # Plot 'close' and 'value' on the first subplot
    ax1.plot(df.index, df['close'], label='Close Price', color=(0.5, 0.5, 0.5))
    ax1.set_ylabel('Close Price')
    ax1.yaxis.grid(True, linestyle='--', linewidth=0.5, color='gray')
    ax1.legend(loc='upper left')

    ax1_2 = ax1.twinx()
    ax1_2.plot(df.index, df['value'], label='Value', color='red')
    ax1_2.set_ylabel('Value')
    ax1_2.legend(loc='upper right')

    # Plot 'cash' on the second subplot
    ax2.plot(df.index, df['cash'], label='Cash', color='orange')
    ax2.set_ylabel('Cash')
    ax2.legend(loc='upper left')
    plt.title('策略回测数据图像')

    # Improve layout and appearance
    fig.tight_layout(pad=5)

    fig.savefig(fig_path)


class FightingSummary:
    def __init__(self, parent: FightingModel):
        self.parent = parent
        if isinstance(self.parent, FightingModel):
            pass
        else:
            raise ValueError("模块传入错误！")
        pass

    def fighting_plan_1(self):
        # 若资产数据、订单数据、交易数据有一项为空
        equity_symbol_num = len(self.parent.equity_data_dc.keys())
        order_symbol_num = len(self.parent.order_data_dc.keys())
        if equity_symbol_num != order_symbol_num:
            # 发送日志报错误，并结束
            info = "两组action数据的symbol数量不一致。"
            self.parent.master.file_manager.log_engine(info, LogName.Running)
            return
        else:
            pass
        if self.parent.result_folder.split('-')[0] == "BT":
            result_dir_path = os.path.join(self.parent.master.file_manager.result_path, ResultFolder.BT.value,
                                           self.parent.result_folder)
        else:
            result_dir_path = os.path.join(self.parent.master.file_manager.result_path, ResultFolder.FHT.value,
                                           self.parent.result_folder)

        md_file_path = os.path.join(result_dir_path, "fighting_plan1.md")
        md_file = MdUtils(file_name=md_file_path)
        md_file.new_line()
        md_file.new_header(1, "简单策略分析报告")
        md_file.write("\n---")
        for symbol in self.parent.equity_data_dc.keys():
            md_file.new_header(2, f"{symbol}回测数据特征描述")
            md_file.write("\n---")
            # 给数据赋新变量名
            equity = self.parent.equity_data_dc[symbol]
            order = self.parent.order_data_dc[symbol]

            # 回测图像
            # （注释）可通过将本次回测对应的market_factor_signal数据呈现至K线图，可详尽查看每一笔交易前后的技术图像
            # 获取结果文件夹下的回测图像
            plot_type = "Fighting回测图像"
            # 生成回测图像并将图像路径填写至base_name
            base_name = "FHTFigure.jpg"
            fig_path = os.path.join(result_dir_path, base_name)
            draw_backtest_figure(equity, fig_path)
            # -------------
            # md插入回测图像
            md_file.new_line()
            md_code = f"![{symbol} {plot_type}](./{base_name})"
            md_file.new_header(3, f"{symbol}回测图像")
            md_file.write(md_code)
            md_file.write("\n---")
            # 净值分析（表格）
            # 总收益率
            total_return = equity['value'].iloc[-1] / equity['value'].iloc[0] - 1

            # 夏普比率
            daily_returns = equity['value'].pct_change().dropna()
            sharpe_ratio = daily_returns.mean() / daily_returns.std() * (252 ** 0.5)  # 假设无风险利率为0

            # 最大回撤
            rolling_max = equity['value'].cummax()
            daily_drawdown = equity['value'] / rolling_max - 1
            max_drawdown = daily_drawdown.min()

            # 订单分析（表格）
            # 累计订单数量
            total_orders = len(order)
            # 单笔交易平均占用行情节点个数
            average_daily_orders = len(equity) / total_orders
            # # 交易分析（表格+频率直方图）
            # # 累计交易数量、单笔交易盈利、盈亏比、交易时长频率分布直方图
            # # 交易数量
            # total_trades = len(trade)
            # # 平均单笔交易盈利
            # average_trade_profit = trade['pnl'].mean()
            # # 盈亏比
            # average_win = trade[trade['pnl'] > 0]['pnl'].sum()
            # average_loss = trade[trade['pnl'] < 0]['pnl'].sum()
            # profit_loss_ratio = average_win / abs(average_loss)
            # # 交易胜率
            # win_rate = len(trade[trade['pnl'] > 0]) / len(trade)

            # 指标列表
            sig_ls = [
                ["指标", "数值", "备注"],
                ["总收益率", round(total_return, 4), "最后净值相对初始净值的涨幅。"],
                ["夏普比率", round(sharpe_ratio, 4), "将单个节点视为一天，而得出的简单夏普比率。"],
                ["最大回撤", round(-max_drawdown, 4), "反应风险。"],
                ["单笔交易平均占用行情个数", round(average_daily_orders, 4), "反应单笔交易的持仓时长。"],
                # ["交易数量", round(total_trades, 4), "交易的数量。"],
                # ["平均单笔交易盈利", round(average_trade_profit, 4), "每笔交易盈利的均值。"],
                # ["盈亏比", round(profit_loss_ratio, 4), "盈利订单总盈利与亏损订单总亏损的比值。"],
                # ["交易胜率", round(win_rate, 4), "盈利订单数量所占总订单数量的比例。"],
            ]
            tab_str_ls = []
            for sig_o in sig_ls:
                tab_str_ls += sig_o
            md_file.new_line()
            md_file.new_header(3, f"{symbol}回测数据")
            md_file.write("\n---")
            md_file.new_table(3, len(sig_ls), tab_str_ls)
            md_file.write("\n---")

        self.parent.master.file_manager.save_md(md_file)
        self.parent.master.file_manager.md2html(md_file_path, True)  # 打开html

        pass

